home *** CD-ROM | disk | FTP | other *** search
- include macros.h
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ │
- ;│ CUBE - A general purpose solver of combinatorial block puzzles │
- ;│ │
- ;│ written by: Steve Gibson │
- ;│ Gibson Research Corporation │
- ;│ 9/18/91 │
- ;│ │
- ;│ Please note: These files were asssembled and linked with Steve │
- ;│ Russell's excellent optimizing assembler (OPTASM) and linker │
- ;│ (OPTLINK). Consequently, if any "conditional jump out-of-range" │
- ;│ errors are received either the files will have to be edited or │
- ;│ an optimizing assembler will have to be used. │
- ;│ - ENJOY! │
- ;│ │
- ;╘══════════════════════════════════════════════════════════════════════════╛
-
- TITLE CUBE
-
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ │
- ;│ CUBE solves Bob's wooden block puzzle. │
- ;│ │
- ;│ ──────────────────────────────────────────────────────────────── │
- ;│ Please see the READ.ME and TECHTALK.TXT files that were included │
- ;│ within the CUBE.EXE self-extracting ZIP file for further details │
- ;│ about the CUBE ... and for information about where you can │
- ;│ purchase the cube puzzle if you'd like to play with it yourself │
- ;│ and assemble it from the program's result. │
- ;│ ──────────────────────────────────────────────────────────────── │
- ;│ │
- ;│ This puzzle consists of a 3x3x3 "master cube" composed of 27 │
- ;│ "sub-cubes." Combinations of sub-cubes are stuck together │
- ;│ forming the nine puzzle pieces. The puzzle is complicated │
- ;│ by the fact that a number of the sub-cubes are cut half, with │
- ;│ different halves stuck to different pieces. This means that │
- ;│ rotating the pieces requires both rotation and translation of │
- ;│ the sub-cubes, rather than just translation as would be the │
- ;│ case if all of the sub-cubes were simple cubes. │
- ;│ │
- ;│ Numbering and Axis legend: │
- ;│ ───────────────────────────────────────────────────────────── │
- ;│ Individual pieces are numbered 0 thru 8. │
- ;│ Positions within the master 3x3x3 cube are numbered 1 thru 27. │
- ;│ Corners of the 2x2x2 sub-cubes are numbered 1 thru 8. │
- ;│ The X axis runs left-to-right through the master cube. │
- ;│ The Y axis runs into and outof the table. │
- ;│ The Z axis runs forward and backward through the master cube. │
- ;│ A positive X rotation flops the cube forward. │
- ;│ A positive Y rotation twists the cube 90 degrees clockwise. │
- ;│ A positive Z rotation flops the cube to the right. │
- ;│ │
- ;╘══════════════════════════════════════════════════════════════════════════╛
-
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ **************** E Q U A T E S A N D M A C R O S *************** │
- ;└──────────────────────────────────────────────────────────────────────────┘
-
- NUMBER_OF_PIECES equ 9 ; puzzle contains nine pieces
- CUBE_LENGTH equ 3
- CUBE_HEIGHT equ 3
- CUBE_DEPTH equ 3
- CUBE_SURFACE equ CUBE_LENGTH * CUBE_HEIGHT
- SUB_CUBE_COUNT equ CUBE_LENGTH * CUBE_HEIGHT * CUBE_DEPTH
- PIECE_DEFINITION_LENGTH equ (OFFSET Piece_2 - OFFSET Piece_1)
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ *************************** S E G M E N T S ************************** │
- ;└──────────────────────────────────────────────────────────────────────────┘
- CodeSeg segment para public 'code'
- assume cs: CodeSeg, ds: CodeSeg, es: CodeSeg, ss: CodeSeg
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ *********************** E N T R Y P O I N T *********************** │
- ;└──────────────────────────────────────────────────────────────────────────┘
- org 0
- StartOfProg equ THIS BYTE
- org 100h
- Entry: jmp SolveIt
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ ***************** P U Z Z L E P I E C E D A T A **************** │
- ;└──────────────────────────────────────────────────────────────────────────┘
-
- PieceDefinitions:
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ The piece definitions specify the shape of the individual │
- ;│ pieces, and their initial position parity. Each of the first │
- ;│ five bytes represents a single sub-cube, with each of the │
- ;│ byte's 8-bits representing wood in the respective corner of │
- ;│ the sub-cube. Thus FF represents a solid cube and AA, CC, │
- ;│ and F0 represents various orientations of half-cubes. ZERO │
- ;│ parity means Dark Wood at the 1,1,1 corner (the first byte) │
- ;│ of the cube's definition. │
- ;│──────────────────────────────────────────────────────────────────────────│
- ;│ 1 2 3 4 5 6 Color Parity │
- ;└──────────────────────────────────────────────────────────────────────────┘
- Piece_1 db 0FFh, 0FFh, 0FFh, 0CCh, 000h, 000h, 0 ; L: short foot
- Piece_2 db 0FFh, 0FFh, 0AAh, 000h, 000h, 0AAh, 0 ; short L with thin foot
- Piece_3 db 0FFh, 0FFh, 000h, 0FFh, 000h, 000h, 0 ; elbow 1
- Piece_4 db 0FFh, 0FFh, 000h, 0FFh, 000h, 000h, 1 ; elbow 2
- Piece_5 db 0FFh, 0FFh, 0AAh, 00Fh, 000h, 000h, 0 ; short L with twisted foot
- Piece_6 db 0FFh, 0FFh, 00Fh, 0CCh, 000h, 000h, 0 ; L: twist head & short foot
- Piece_7 db 0FFh, 0FFh, 00Fh, 000h, 000h, 000h, 1 ; I: twisted head
- Piece_8 db 0FFh, 0FFh, 0F0h, 0CCh, 000h, 000h, 0 ; L: lifted twist hd, shrt ft
- Piece_9 db 0FFh, 0FFh, 0CCh, 000h, 0F0h, 000h, 0 ; T: twist head, lifted stem
-
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ These Spin Tables manage the rotation of the 2x2x2 sub-cubes │
- ;│ within the larger 3x3x3 master cube. Each sub-cube contains │
- ;│ eight items, representing wood in each of its eight corners. │
- ;│ Each table consists of 8 bytes, where the ON bit in the byte │
- ;│ specifies where the bit mapped into the byte will move when │
- ;│ the 2x2x2 cube is subjected to a positive rotation about the │
- ;│ specified axis. │
- ;│ │
- ;│ Destination: 12345678 12345678 12345678 12345678 │
- ;└──────────────────────────────────────────────────────────────────────────┘
- Spin_X_Table db 00001000b, 00000100b, 10000000b, 01000000b
- db 00000010b, 00000001b, 00100000b, 00010000b
- ;────────────────────────────────────────────────────────────────────────────
- Spin_Y_Table db 01000000b, 00010000b, 10000000b, 00100000b
- db 00000100b, 00000001b, 00001000b, 00000010b
- ;────────────────────────────────────────────────────────────────────────────
- Spin_Z_Table db 01000000b, 00000100b, 00010000b, 00000001b
- db 10000000b, 00001000b, 00100000b, 00000010b
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ These Rotate Tables manage the translation of the 2x2x2 │
- ;│ sub-cubes within the larger 3x3x3 master cube. When the │
- ;│ master cube is rotated each of the sub-cubes is rotated │
- ;│ based upon the Spin tables above, then the sub-cube is │
- ;│ translated, relocating its position within the 3x3x3 master │
- ;│ cube. Each entry in the table below specifies which one of │
- ;│ the 27 sub-cubes will occupy the respective location │
- ;│ within the new master cube after rotation. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- Rotate_X_Table db 7, 8, 9, 16, 17, 18, 25, 26, 27 ; 1- 9
- db 4, 5, 6, 13, 14, 15, 22, 23, 24 ; 10-18
- db 1, 2, 3, 10, 11, 12, 19, 20, 21 ; 19-27
- ;────────────────────────────────────────────────────────────────────────────
- Rotate_Y_Table db 7, 4, 1, 8, 5, 2, 9, 6, 3 ; 1- 9
- db 16, 13, 10, 17, 14, 11, 18, 15, 12 ; 10-18
- db 25, 22, 19, 26, 23, 20, 27, 24, 21 ; 19-27
- ;────────────────────────────────────────────────────────────────────────────
- Rotate_Z_Table db 19, 10, 1, 22, 13, 4, 25, 16, 7 ; 1- 9
- db 20, 11, 2, 23, 14, 5, 26, 17, 8 ; 10-18
- db 21, 12, 3, 24, 15, 6, 27, 18, 9 ; 19-27
-
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ These Translation Tables manage the translation of the sub-cubes │
- ;│ within the larger 3x3x3 master cube. When the master cube is │
- ;│ translated, each of the sub-cubes is relocated within the 3x3x3 │
- ;│ master cube. Each entry in the table below specifies which one of │
- ;│ the 27 sub-cubes will occupy the respective location within the │
- ;│ new master cube after translation. A ZERO entry means that the │
- ;│ location will be completely empty after translation. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- Translate_X0_Table db 2, 3, 0, 5, 6, 0, 8, 9, 0 ; 1- 9
- db 11, 12, 0, 14, 15, 0, 17, 18, 0 ; 10-18
- db 20, 21, 0, 23, 24, 0, 26, 27, 0 ; 19-27
- ;────────────────────────────────────────────────────────────────────────────
- Translate_X1_Table db 0, 1, 2, 0, 4, 5, 0, 7, 8 ; 1- 9
- db 0, 10, 11, 0, 13, 14, 0, 16, 17 ; 10-18
- db 0, 19, 20, 0, 22, 23, 0, 25, 26 ; 19-27
- ;────────────────────────────────────────────────────────────────────────────
- Translate_Y0_Table db 10, 11, 12, 13, 14, 15, 16, 17, 18 ; 1- 9
- db 19, 20, 21, 22, 23, 24, 25, 26, 27 ; 10-18
- db 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 19-27
- ;────────────────────────────────────────────────────────────────────────────
- Translate_Y1_Table db 0, 0, 0, 0, 0, 0, 0, 0, 0 ; 1- 9
- db 1, 2, 3, 4, 5, 6, 7, 8, 9 ; 10-18
- db 10, 11, 12, 13, 14, 15, 16, 17, 18 ; 19-27
- ;────────────────────────────────────────────────────────────────────────────
- Translate_Z0_Table db 4, 5, 6, 7, 8, 9, 0, 0, 0 ; 1- 9
- db 13, 14, 15, 16, 17, 18, 0, 0, 0 ; 10-18
- db 22, 23, 24, 25, 26, 27, 0, 0, 0 ; 19-27
- ;────────────────────────────────────────────────────────────────────────────
- Translate_Z1_Table db 0, 0, 0, 1, 2, 3, 4, 5, 6 ; 1- 9
- db 0, 0, 0, 10, 11, 12, 13, 14, 15 ; 10-18
- db 0, 0, 0, 19, 20, 21, 22, 23, 24 ; 19-27
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ These Surface Tables specify which sub-cubes lie upon each of the │
- ;│ six surfaces of the master cube. This is used by the translation │
- ;│ logic to determine whether an object may be translated into the │
- ;│ empty surface of the master cube. Each table lists the nine sub- │
- ;│ cubes lying on the respecting face of the master cube. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- Surface_X0_Table db 1, 4, 7, 10, 13, 16, 19, 22, 25
- Surface_X1_Table db 3, 6, 9, 12, 15, 18, 21, 24, 27
- ;────────────────────────────────────────────────────────────────────────────
- Surface_Y0_Table db 1, 2, 3, 4, 5, 6, 7, 8, 9
- Surface_Y1_Table db 19, 20, 21, 22, 23, 24, 25, 26, 27
- ;────────────────────────────────────────────────────────────────────────────
- Surface_Z0_Table db 1, 2, 3, 10, 11, 12, 19, 20, 21
- Surface_Z1_Table db 7, 8, 9, 16, 17, 18, 25, 26, 27
-
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ ************ M I S C E L L A N E O U S V A R I A B L E S ************ │
- ;└──────────────────────────────────────────────────────────────────────────┘
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ Indexed by piece number [0..8] This is a table of the number of images │
- ;│ we've generated for each piece. The image generator increments these │
- ;│ values as it stores non-redundant piece images, and the tree exploring │
- ;│ routine uses this to explore the resulting image tables. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- PieceImageCounts dw NUMBER_OF_PIECES dup (0)
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ Indexed by piece number [0..8] This is a table of OFFSETS into the │
- ;│ PieceTable (but relative to DS) for each set of piece image tables. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- PieceTableOffsets dw NUMBER_OF_PIECES dup (0)
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ This is the offset of the NEXT AVAILABLE BYTE in the PieceTable. │
- ;│ Piece image tables are allocated from this point and it is augmented │
- ;│ by the size of a table: SUB_CUBE_COUNT+1. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- CurrentTableBase dw PieceTable ; initialize at bottom
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ These are general usage working piece storage tables. The Working │
- ;│ Piece Table contains the piece position we're currently operating upon. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- WorkingPieceTable db SUB_CUBE_COUNT+1 dup(0)
- TempPieceTable db SUB_CUBE_COUNT+1 dup(0)
- XSaveTable db SUB_CUBE_COUNT+1 dup(0)
- YSaveTable db SUB_CUBE_COUNT+1 dup(0)
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ The number of the Piece we're currently operating upon. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- CurrentPiece dw 0
-
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ ********** S T A R T O F E X E C U T A B L E C O D E ********** │
- ;└──────────────────────────────────────────────────────────────────────────┘
- SolveIt: cld ; initialize things ...
- mov sp, OFFSET TopOfStack ; switch to internal stack
- call SetupTheSystem
-
- mov CurrentPiece, 0 ; start with the first one
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ We build all possible positions of each puzzle piece ... This is all │
- ;│ 24 orientations of each the piece in each translated location. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ To process a piece, we load the piece's definition into the │
- ;│ WorkingTable, then give it a good spin! │
- ;└──────────────────────────────────────────────────────────────────────────┘
- ProcessAPiece: mov ax, PIECE_DEFINITION_LENGTH ; don't move parity
- mov bx, CurrentPiece
- mov cx, ax ; save the length for the move
- dec cx ; move one less than the len
- mul bx ; get piece definition
- add ax, OFFSET PieceDefinitions
- mov si, ax
- mov di, OFFSET WorkingPieceTable
- rep movsb ; load the table
- zero al
- mov cx, SUB_CUBE_COUNT - (PIECE_DEFINITION_LENGTH - 1)
- rep stosb ; and clear the rest
- movsb ; add the parity to the end
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ Now we save the CurrentTableBase as the base for this piece │
- ;└──────────────────────────────────────────────────────────────────────────┘
-
- double bx ; turn piece into a word ptr
- mov ax, CurrentTableBase
- mov PieceTableOffsets[bx], ax
- mov PieceImageCounts[bx], 0 ; clear the count
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ Now we store all 24 orientations of the piece in every │
- ;│ translation. The sequence of orientation explorations is: │
- ;│ 3*(3*Y,X) -<Y,X,X>- 3*(3*Y,X) │
- ;└──────────────────────────────────────────────────────────────────────────┘
-
- call ExploreHalf ; flesh out half the orientations
- call Rotate_Y ; flip over to the second half
- call Rotate_X_Twice
- call ExploreHalf ; and flesh out the second half
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ Now we process the next piece ... if one exists │
- ;└──────────────────────────────────────────────────────────────────────────┘
- inc CurrentPiece ; [0..8]
- cmp CurrentPiece, NUMBER_OF_PIECES
- jb ProcessAPiece
-
-
- ;┌──────────────────────────────────────────────────────────────────────────┐
- ;│ No more pieces! ... so let's get to work! │
- ;│ We'll exhaustively search through the entire tree ... │
- ;└──────────────────────────────────────────────────────────────────────────┘
- jmp SearchTheTree
-
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ ************************ S U B R O U T I N E S *********************** │
- ;╘══════════════════════════════════════════════════════════════════════════╛
-
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ This routine makes 12 calls to "StoreTranslations" with the │
- ;│ puzzle piece in a different orientation each time. It's │
- ;│ called twice, once for each half of the possible orientations. │
- ;│ The sequence of rotation calls is: 3*(3*Y,X) │
- ;└──────────────────────────────────────────────────────────────────────────┘
- ExploreHalf: mov cx, 3
- MiddleLoop: call StoreAllTrans ; store translations @ current orient
- push cx
- mov cx, 3
- ;────────────────────────────────────────────────────────────────────────────
- InnerLoop: call Rotate_Y
- call StoreAllTrans
- loop InnerLoop
- call Rotate_X
- pop cx
- loop MiddleLoop
- ret
-
-
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Given the current orientation of the current WorkingPiece, build legal │
- ;│ translations, storing unique ones in the piece's position image table. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- StoreAllTrans: push cx
- call SlideToOrigin ; push the piece -> X0, Y0, Z0
- jmp ExploreX
-
- MoveOnX: call TranslateX1
- ExploreX: mov di, OFFSET XSaveTable
- call SavePieceState ; stack the piece's location
- jmp ExploreY
- ;════════════════════════════════════════════════════════════════════════════
- MoveOnY: call TranslateY1
- ExploreY: mov di, OFFSET YSaveTable
- call SavePieceState ; stack the piece's location
- jmp ExploreZ
-
- ;────────────────────────────────────────────────────────────────────────────
- MoveOnZ: call TranslateZ1
- ExploreZ: test WorkingPieceTable[SUB_CUBE_COUNT], 1 ; check parity
- jnz SkipThisSave
- call StoreNewPosition
- SkipThisSave: mov bx, OFFSET Surface_Z1_Table
- call TestSurface
- jz MoveOnZ
- ;────────────────────────────────────────────────────────────────────────────
- mov si, OFFSET YSaveTable
- call RestorePieceState ; recover the piece's loc.
- mov bx, OFFSET Surface_Y1_Table
- call TestSurface
- jz MoveOnY
- ;════════════════════════════════════════════════════════════════════════════
- mov si, OFFSET XSaveTable
- call RestorePieceState ; recover the piece's loc.
- mov bx, OFFSET Surface_X1_Table
- call TestSurface
- jz MoveOnX
- pop cx
- ret
-
-
- StoreNewPosition:
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Save the unique position (from WorkingPositionTable) into │
- ;│ the piece's position memory. │
- ;│ │
- ;│ ax - overall iteration counter │
- ;│ bx - destination renewal │
- ;│ cx - rep count │
- ;│ dx - rep save │
- ;│ si source index │
- ;│ di dest index │
- ;│ bp - source renewal │
- ;└──────────────────────────────────────────────────────────────────────────┘
- mov bx, CurrentPiece
- double bx ; make word index
- mov ax, PieceImageCounts[bx] ; get image count
- mov bx, PieceTableOffsets[bx] ; get table base
- mov bp, OFFSET WorkingPieceTable ; get source index
- mov dx, (SUB_CUBE_COUNT+1)/2 ; (14 compares)
-
- ;────────────────────────────────────────────────────────────────────────────
- CheckForUnique: mov cx, dx ; get the table size to compare
- mov si, bp ; renew the source location
- mov di, bx ; and get the table loc
- check ax ; do we have any more?
- jz ItsUnique ; nope, so move rather than compare
-
- repe cmpsw ; are they the same?
- je NotUnique
-
- add bx, dx
- add bx, dx ; point to the next table
- dec ax ; decrement the number remaining
- jmp CheckForUnique ; check the next image
-
-
- ;────────────────────────────────────────────────────────────────────────────
- ItsUnique: rep movsw ; copy the new position ...
- mov CurrentTableBase, di ; update the base pointer
- mov bx, CurrentPiece ; get index
- double bx ; make word index
- inc PieceImageCounts[bx] ; and increment the count
- call ShowImageCount
- ;────────────────────────────────────────────────────────────────────────────
- NotUnique: ret
-
-
- SavePieceState:
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Save the WorkingPieceTable piece state │
- ;│ in the table pointed to by [DI]. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- mov si, OFFSET WorkingPieceTable
- jmp CopyPieceTable
-
-
- RestorePieceState:
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Restore the WorkingPieceTable piece state │
- ;│ from the table pointed to by [SI]. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- mov di, OFFSET WorkingPieceTable
- CopyPieceTable: mov cx, (SUB_CUBE_COUNT+1)/2 ; move words
- rep movsw
- ret
-
-
- SlideToOrigin:
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Translate the current piece as far as it │
- ;│ will go in the X0, Y0, and Z0 directions. │
- ;└──────────────────────────────────────────────────────────────────────────┘
- SlideXBack: mov bx, OFFSET Surface_X0_Table
- call TestSurface
- jnz SlideYBack
- call TranslateX0
- jmp SlideXBack
- ;────────────────────────────────────────────────────────────────────────────
- SlideYBack: mov bx, OFFSET Surface_Y0_Table
- call TestSurface
- jnz SlideZBack
- call TranslateY0
- jmp SlideYBack
- ;────────────────────────────────────────────────────────────────────────────
- SlideZBack: mov bx, OFFSET Surface_Z0_Table
- call TestSurface
- jnz Originated
- call TranslateZ0
- jmp SlideZBack
- ;────────────────────────────────────────────────────────────────────────────
- Originated: ret
-
-
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ These entry-points slide the puzzle piece one │
- ;│ cube in the appropriate direction │
- ;└──────────────────────────────────────────────────────────────────────────┘
- TranslateX0: mov bx, OFFSET Translate_X0_Table
- jmp ToggleParity
- TranslateX1: mov bx, OFFSET Translate_X1_Table
- jmp ToggleParity
- TranslateY0: mov bx, OFFSET Translate_Y0_Table
- jmp ToggleParity
- TranslateY1: mov bx, OFFSET Translate_Y1_Table
- jmp ToggleParity
- TranslateZ0: mov bx, OFFSET Translate_Z0_Table
- jmp ToggleParity
- TranslateZ1: mov bx, OFFSET Translate_Z1_Table
- jmp ToggleParity
-
- ;────────────────────────────────────────────────────────────────────────────
- Rotate_X_Twice: Call Rotate_X ; execute below twice
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Flop the WorkingPiece definition forward │
- ;│ The X axis runs left-to-right through the cube │
- ;└──────────────────────────────────────────────────────────────────────────┘
- Rotate_X: mov bx, OFFSET Spin_X_Table ; the X spin spec
- call SpinCubes ; spin individuals
- mov bx, OFFSET Rotate_X_Table ; the X rotate spec
- jmp MoveCubes
-
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Twist the WorkingPiece definition clockwise │
- ;│ The Y axis runs top-to-bottom through the cube │
- ;└──────────────────────────────────────────────────────────────────────────┘
- Rotate_Y: mov bx, OFFSET Spin_Y_Table ; the X spin spec
- call SpinCubes ; spin individuals
- mov bx, OFFSET Rotate_Y_Table ; the X rotate spec
- jmp MoveCubes
-
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Flop the WorkingPiece definition to the right │
- ;│ The Z axis runs front-to-back through the cube │
- ;└──────────────────────────────────────────────────────────────────────────┘
- Rotate_Z: mov bx, OFFSET Spin_Z_Table ; the X spin spec
- call SpinCubes ; spin individuals
- mov bx, OFFSET Rotate_Z_Table ; the X rotate spec
- jmp MoveCubes
-
-
- ToggleParity:
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ This entry to MoveCubes toggles the │
- ;│ parity bit in the WorkingPieceTable │
- ;└──────────────────────────────────────────────────────────────────────────┘
- xor WorkingPieceTable[SUB_CUBE_COUNT], 1 ; toggle bit
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Rotate the WorkingPiece sub-cubes about the central │
- ;│ axis using the rotation table pointed to by BX │
- ;└──────────────────────────────────────────────────────────────────────────┘
- MoveCubes: push cx
- mov cx, SUB_CUBE_COUNT
- mov di, OFFSET TempPieceTable
- push di ; save temp piece table location
- ;────────────────────────────────────────────────────────────────────────────
- NextCube: mov si, [bx] ; get the item to move
- and si, 00FFh ; the index is byte size
- mov al, WorkingPieceTable[si-1] ; 0-base it
- jnz MoveCube ; did we get a zero?
- zero al ; yep, so clear the block...
- MoveCube: stosb ; save the new piece definition
- inc bx ; point to next table entry
- loop NextCube
- ;────────────────────────────────────────────────────────────────────────────
- mov cx, SUB_CUBE_COUNT
- pop si ; recover the temp piece location
- mov di, OFFSET WorkingPieceTable
- rep movsb ; and copy the temp -> piece
- pop cx
- ret
-
-
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Spin the individual WorkingPiece sub-cubes about │
- ;│ their own axis using the spin table pointed to by BX │
- ;└──────────────────────────────────────────────────────────────────────────┘
- SpinCubes: push cx
- mov di, OFFSET WorkingPieceTable
- mov cx, SUB_CUBE_COUNT
- SpinCorner: push cx ; save cube counter
- mov ah, [di] ; get the cube's bits
- zero al ; zero result catcher
- mov cx, 8 ; spin 8 bits
- DoCorner: shl ah, 1 ; get the next bit
- jnc NextCorner
- or al, [bx] ; or in the bit specified
- NextCorner: inc bx ; get next mask
- loop DoCorner ; and do eight of them
- stosb ; save the result and inc ...
- sub bx, 8 ; and re-point BX to the table
- pop cx ; recover the cube counter
- loop SpinCorner
- pop cx
- ret
-
-
-
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Test the WorkingPieceTable for "wood" along the surface │
- ;│ specified in the table pointed to by BX, return with FLAGS │
- ;└──────────────────────────────────────────────────────────────────────────┘
- TestSurface: mov ax, 00FFh ; byte mask
- mov cx, CUBE_SURFACE ; nine sub-cubes on surface
- ;────────────────────────────────────────────────────────────────────────────
- NextSubCube: mov si, [bx] ; get the item to move
- and si, ax ; the index is only a byte long
- test BYTE PTR WorkingPieceTable[si-1], al ; check for wood
- jnz SurfaceTested
- inc bx ; prepare for the next one
- loop NextSubCube
- zero cx ; set flags to "ZERO"
- SurfaceTested: ret
-
-
- WaitForKeypress:
- ;╒══════════════════════════════════════════════════════════════════════════╕
- ;│ Waits for a keypress from the keyboard ... │
- ;└──────────────────────────────────────────────────────────────────────────┘
- mov ah, GETKEY_WAIT
- int KEYBOARD_IO
- ret
-
- ;────────────────────────────────────────────────────────────────────────────
- include cubesys.inc ; include the cube screen file here
- include cubesrch.inc ; include the cube search algorithm
- ;════════════════════════════════════════════════════════════════════════════
- InitScreenBuffer = THIS BYTE
- PieceTable = InitScreenBuffer + SCREEN_LENGTH
- BottomOfStack = PieceTable + (SUB_CUBE_COUNT+1) * (8*72+96)
- TopOfStack = BottomOfStack + STACK_DEPTH
- ;════════════════════════════════════════════════════════════════════════════
- CodeSeg ends
- end Entry
-
-